home *** CD-ROM | disk | FTP | other *** search
/ Collection of Tools & Utilities / Collection of Tools and Utilities.iso / edit / dte5_1.zip / FINDREP.C < prev    next >
C/C++ Source or Header  |  1991-02-06  |  34KB  |  1,133 lines

  1. /*
  2.  * Written by Douglas Thomson (1989/1990)
  3.  *
  4.  * This source code is released into the public domain.
  5.  */
  6.  
  7. /*
  8.  * Name:    dte - Doug's Text Editor program - find/replace module
  9.  * Purpose: This file contains the functions relating to finding text
  10.  *           and replacing text.
  11.  *          It also contains the code for moving the cursor to various
  12.  *           other positions in the file.
  13.  * File:    findrep.c
  14.  * Author:  Douglas Thomson
  15.  * System:  this file is intended to be system-independent
  16.  * Date:    October 1, 1989
  17.  */
  18.  
  19. #ifdef HPXL
  20. #include "commonh"
  21. #include "findreph"
  22. #include "utilsh"
  23. #else
  24. #include "common.h"
  25. #include "findrep.h"
  26. #include "utils.h"
  27. #endif
  28.  
  29. /*
  30.  * prototypes for all functions in this file
  31.  */
  32. int set_flags ARGS((char *flag_str, int *flags, int *count));
  33. int get_flags ARGS((int lines));
  34. int mystrcmp ARGS((char *s1, char *s2));
  35. int mystrcmpi ARGS((char *s1, char *s2));
  36. void on_screen ARGS((windows *window, text_ptr cursor, int last));
  37. void do_replace ARGS((windows *window, text_ptr start));
  38. void do_last ARGS((windows *window));
  39. void find_string ARGS((windows *window));
  40. void replace_string ARGS((windows *window));
  41. void goto_prep ARGS((windows *window));
  42. void goto_complete ARGS((windows *window, text_ptr cursor));
  43. void goto_marker ARGS((windows *window, int n));
  44. void goto_top_file ARGS((windows *window));
  45. void goto_end_file ARGS((windows *window));
  46. text_ptr scan_forward ARGS((text_ptr start, char *opp, char *target));
  47. text_ptr scan_backward ARGS((text_ptr start, char *opp, char *target));
  48. void match_pair ARGS((windows *window, int forward));
  49. void goto_line ARGS((windows *window));
  50.  
  51. /*
  52.  * find and replace flags
  53.  */
  54. #define F_BACKWARD 0x01 /* search backwards through file */
  55. #define F_GLOBAL   0x02 /* search entire file */
  56. #define F_LOCAL    0x04 /* search only marked block */
  57. #define F_AUTO     0x08 /* behave as if user always answered yes */
  58. #define F_IGNORE   0x10 /* ignore case differences */
  59. #define F_WORD     0x20 /* match whole words only */
  60. #define F_MATCH    0x40 /* match the case of the text being replaced */
  61.  
  62. /*
  63.  * Name:    set_flags
  64.  * Purpose: To set up find and replace flags.
  65.  * Date:    October 1, 1989
  66.  * Passed:  flag_str:   the flags chosen by the user
  67.  * Returns: flags:      the equivalent binary flags
  68.  *          count:      the repeat count embedded in the flags
  69.  *          TRUE if flags were OK, FALSE otherwise
  70.  */
  71. int set_flags(flag_str, flags, count)
  72. char *flag_str;
  73. int *flags;
  74. int *count;
  75. {
  76.     char *p;    /* used to scan through flag_str for flags */
  77.  
  78.     /*
  79.      * start with no flags set, then add those chosen
  80.      */
  81.     *flags = 0;
  82.  
  83.     /*
  84.      * assume just a single find / replace required
  85.      */
  86.     *count = 1;
  87.  
  88.     /*
  89.      * scan flag_str to work out which flags were chosen
  90.      */
  91.     for (p=flag_str; *p; ++p) {
  92.         if (isdigit(*p)) {
  93.             /*
  94.              * extract an embedded repeat count
  95.              */
  96.             *count = atoi(p);
  97.             while (isdigit(*++p)) {
  98.                 ;
  99.             }
  100.             --p;
  101.             if (*count <= 0) {
  102.                 error(WARNING, "bad repeat count: %d", *count);
  103.                 *count = 1;
  104.                 return FALSE;
  105.             }
  106.         }
  107.         else if ((*p = toupper(*p)) == 'B') {
  108.             *flags |= F_BACKWARD;
  109.         }
  110.         else if (*p == 'G') {
  111.             *flags |= F_GLOBAL;
  112.             *count = GLOB_COUNT;
  113.         }
  114.         else if (*p == 'L') {
  115.             *flags |= F_LOCAL;
  116.             *count = GLOB_COUNT;
  117.         }
  118.         else if (*p == 'N') {
  119.             *flags |= F_AUTO;
  120.         }
  121.         else if (*p == 'U') {
  122.             *flags |= F_IGNORE;
  123.         }
  124.         else if (*p == 'W') {
  125.             *flags |= F_WORD;
  126.         }
  127.         else if (*p == 'M') {
  128.             *flags |= F_MATCH;
  129.         }
  130.         else {
  131.             error(WARNING, "unknown flag: %c", *p);
  132.             return FALSE;
  133.         }
  134.     }
  135.     return TRUE;
  136. }
  137.  
  138. /*
  139.  * Name:    get_flags
  140.  * Purpose: To input find and replace flags.
  141.  * Date:    October 1, 1989
  142.  * Passed:  lines:  no. of lines up from bottom of screen
  143.  * Returns: [g_status.flags]:        binary flags set
  144.  *          [g_status.flag_str]:     flags as character string
  145.  *          [g_status.search_count]: repeat find count
  146.  *          OK if flags were entered, ERROR if user wanted to abort
  147.  */
  148. int get_flags(lines)
  149. int lines;
  150. {
  151.     char flag_str[MAX_COLS]; /* temporary copy of g_status.flag_str */
  152.     int flags;               /* temporary copy of g_status.flags */
  153.     int count;               /* temporary copy of g_status.count */
  154.  
  155.     /*
  156.      * use the previous flags as the default
  157.      */
  158.     strcpy(flag_str, g_status.flag_str);
  159.  
  160.     /*
  161.      * keep on asking for flags until something acceptable is entered
  162.      */
  163.     for (;;) {
  164.         if (get_name("Options (B,G,L,M,N,n,U,W): ", lines, flag_str) !=
  165.                 OK) {
  166.             return ERROR;
  167.         }
  168.         if (set_flags(flag_str, &flags, &count)) {
  169.             break;
  170.         }
  171.     }
  172.  
  173.     g_status.flags = flags;
  174.     g_status.search_count = count;
  175.     strcpy(g_status.flag_str, flag_str);
  176.     return OK;
  177. }
  178.  
  179. /*
  180.  * Name:    mystrcmp
  181.  * Purpose: To compare two strings up to the length of the first.
  182.  * Date:    October 1, 1989
  183.  * Passed:  s1: first string to compare
  184.  *          s2: second string to compare
  185.  * Returns: 0 if strings match
  186.  *          <0 if s1 < s2
  187.  *          >0 if s1 > s2
  188.  */
  189. int mystrcmp(s1, s2)
  190. char *s1;
  191. char *s2;
  192. {
  193.     for(;;) {
  194.         if (*s1 == '\0') {
  195.             return 0;
  196.         }
  197.         if (*s1 != *s2) {
  198.             return *s1 - *s2;
  199.         }
  200.         ++s1;
  201.         ++s2;
  202.     }
  203. }
  204.  
  205. /*
  206.  * Name:    mystrcmpi
  207.  * Purpose: To compare two strings up to the length of the first, ignoring
  208.  *           case.
  209.  * Date:    October 1, 1989
  210.  * Passed:  s1: first string to compare
  211.  *          s2: second string to compare
  212.  * Returns: 0 if strings match
  213.  *          <0 if s1 < s2
  214.  *          >0 if s1 > s2
  215.  */
  216. int mystrcmpi(s1, s2)
  217. char *s1;
  218. char *s2;
  219. {
  220.     for(;;) {
  221.         if (*s1 == '\0') {
  222.             return 0;
  223.         }
  224.         if (tolower(*s1) != tolower(*s2)) {
  225.             return tolower(*s1) - tolower(*s2);
  226.         }
  227.         ++s1;
  228.         ++s2;
  229.     }
  230. }
  231.  
  232. /*
  233.  * Name:    on_screen
  234.  * Purpose: To move the cursor to a new position, without redrawing the
  235.  *           window unless the new position is off the window.
  236.  * Date:    October 1, 1989
  237.  * Passed:  window: information allowing access to current window etc
  238.  *          cursor: the new target position in the text
  239.  *          last:   the last line considered to be on the screen (this
  240.  *                   only affects the bottom window)
  241.  */
  242. void on_screen(window, cursor, last)
  243. windows *window;
  244. text_ptr cursor;
  245. int last;
  246. {
  247.     text_ptr p;  /* used to scan from current cursor towards new one */
  248.     int line;    /* used to count screen line */
  249.  
  250.     /*
  251.      * if this is the bottom window displayed, then some lines at the
  252.      *  bottom may need to be reserved for messages.
  253.      * Otherwise, the last line available is simply the bottom line used
  254.      *  for the window.
  255.      */
  256.     last = min(g_display.nlines-last-1, window->bottom_line);
  257.  
  258.     line = window->cline;
  259.     if (window->cursor >= cursor) {
  260.         /*
  261.          * new cursor position is above old one
  262.          */
  263.         for (p=window->cursor; ; p--) {
  264.             if (*p == '\n') {
  265.                 --line;
  266.             }
  267.             if (line < window->top_line) {
  268.                 /*
  269.                  * off top of screen, so place in middle of display
  270.                  */
  271.                 window->cline = window->place_line;
  272.  
  273.                 /*
  274.                  * now check that we are not wasting the top part of the
  275.                  *  screen
  276.                  */
  277.                 line = window->cline;
  278.                 for (p=cursor; ; p--) {
  279.                     if (*p == '\n') {
  280.                         --line;
  281.                     }
  282.                     if (*p